package com.aier.common.common;


import java.io.ByteArrayOutputStream;  
import java.io.IOException;  
import java.io.OutputStream; 

public class Base64 {
    private static final char[] legalChars =   
                "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();  
          
    /** 
     * data[]进行编码 
     *  
     * @param data 
     * @return 
     */  
    public static String encode(byte[] data) {  
        int start = 0;  
        int len = data.length;  
        StringBuffer buf = new StringBuffer(data.length * Constant.num_3 / 2);  
  
        int end = len - Constant.num_3;  
        int i = start;  
        int n = 0;  
  
        while (i <= end) {
            int temp = ((data[i] & Constant.num_0ff) << Constant.num_16)  
                    | ((data[i + 1] & Constant.num_0ff) << Constant.num_8);
            int d = temp | (data[i + 2] & Constant.num_0ff);  
  
            buf.append(legalChars[(d >> Constant.num_18) & Constant.num_63]);  
            buf.append(legalChars[(d >> Constant.num_12) & Constant.num_63]);  
            buf.append(legalChars[(d >> Constant.num_6) & Constant.num_63]);  
            buf.append(legalChars[d & Constant.num_63]);  
  
            i += Constant.num_3;  
  
            if (n++ >= Constant.num_14) {  
                n = 0;  
                buf.append(" ");  
            }  
        }  
  
        if (i == start + len - 2) {  
            int d = ((data[i] & Constant.num_0ff) << Constant.num_16)  
                    | ((data[i + 1] & Constant.num_255) << Constant.num_8);  
  
            buf.append(legalChars[(d >> Constant.num_18) & Constant.num_63]);  
            buf.append(legalChars[(d >> Constant.num_12) & Constant.num_63]);  
            buf.append(legalChars[(d >> Constant.num_6) & Constant.num_63]);  
            buf.append("=");  
        } else if (i == start + len - 1) {  
            int d = (data[i] & Constant.num_0ff) << Constant.num_16;  
  
            buf.append(legalChars[(d >> Constant.num_18) & Constant.num_63]);  
            buf.append(legalChars[(d >> Constant.num_12) & Constant.num_63]);  
            buf.append("==");  
        }  
  
        return buf.toString();  
    }  
  
    public static byte[] decode(String s) {  
  
        ByteArrayOutputStream bos = new ByteArrayOutputStream();  
        try {  
            decode(s, bos);  
        } catch (IOException e) {  
            throw new RuntimeException();  
        }  
        byte[] decodedBytes = bos.toByteArray();  
        try {  
            bos.close();  
            bos = null;  
        } catch (IOException ex) {  
            System.err.println("Error while decoding BASE64: " + ex.toString());  
        }  
        return decodedBytes;  
    }  
  
    private static void decode(String s, OutputStream os) throws IOException {  
        int i = 0;  
  
        int len = s.length();  
  
        while (true) {  
            while (i < len && s.charAt(i) <= ' ') { 
                i++;  
            }
            if (i == len) {  
                break;  
            }
            int tri = (decode(s.charAt(i)) << Constant.num_18)  
                    + (decode(s.charAt(i + 1)) << Constant.num_12)  
                    + (decode(s.charAt(i + 2)) << Constant.num_6)  
                    + (decode(s.charAt(i + Constant.num_3)));  
  
            os.write((tri >> Constant.num_16) & Constant.num_255);  
            if (s.charAt(i + 2) == '=') {  
                break; 
            }
            os.write((tri >> Constant.num_8) & Constant.num_255);  
            if (s.charAt(i + Constant.num_3) == '=') {  
                break;  
            }
            os.write(tri & Constant.num_255);  
  
            i += Constant.num_4;  
        }  
    }  
  
    private static int decode(char c) {  
        if (c >= 'A' && c <= 'Z') {  
            return c - Constant.num_65;  
        } else if (c >= 'a' && c <= 'z') {  
            return c - Constant.num_97 + Constant.num_26;  
        } else if (c >= '0' && c <= '9') {  
            return c - Constant.num_48 + Constant.num_26 + Constant.num_26;  
        } else {  
            switch (c) {  
                case '+':  
                    return Constant.num_62;  
                case '/':  
                    return Constant.num_63;  
                case '=':  
                    return 0;  
                default:  
                    throw new RuntimeException("unexpected code: " + c);  
            }  
        }
    }  
}
